#include "Game.h"
#include "ModeLobby.h"

#include "Value.h"

using namespace GTL;
using namespace GTL::Engine;
using namespace GTL::Strings;

inline Point TT(int t) { return Point(t%64, t/64)*32.0f; }
inline Rect RR(int t) { return Rect::CreateFromPosAndSize((t%64)*32.0f, (t/64)*32.0f, 32.0f, 32.0f); }
inline Rect TA(Point p) { return Rect(p, p+Point(32.0f, 32.0f)); }
inline Rect TA(float x, float y) { return Rect(x, y, x+32.0f, y+32.0f); }

int ModeLobby::Draw( float dt )
{
	Backend->ClearScreen(ColorRGBA(0,0,0,1));

	fMain->DrawText(Point(490, 40), "Players:");
	size_t pc = 0;
	for (size_t i=0; i<ParentGame->Players.size(); i++)
	{
		SummonerGame::Player& pl = ParentGame->Players[i];
		
		pc++;
		
		fMain->DrawText(Point(500, 50 + pc*40), ("#"+Just::IntToString(pc)).c_str());
		int plgf = pl.ID%15;
		plgf = 10+(64*(plgf/3))+(plgf%3);
		ParentGame->iTiles->Draw(RR(plgf), TA(520, 50+pc*40));
		fMain->DrawText(Point(570, 50 + pc*40), pl.Name.c_str());
	}


	return 0;
}

int ModeLobby::Load()
{
	net = (NetworkService*)ParentGame->GetService("Network");

	net->SendToServer("{type=conn,name="+AddSlashes(ParentGame->PlayerName)+"}");

	return 0;
}

using namespace GTL::Engine::GUI;
using namespace GTL::Structures;

int ModeLobby::Event( GameEvent event ) 
{
	if (event.EventID == GUI::Event::Click)
	{
		if (event.SenderControl()->Name == "ready")
		{
			GUI::Button* b = (GUI::Button*)event.SenderControl();
			DataNodeWilson w;
			w["type"] = "ready";
			w["val"] = b->IsActive()?"yes":"no";
			net->SendToServer(w);
		} 
		else if (event.SenderControl()->Group == "max players")
		{
			ParentGame->MaxPlayers = Just::StringToInt(event.SenderControl()->Name);
		}
	}
	else if (event.EventID == GUI::Event::KeyPressed && event.SenderControl()->Name == "text" && event.AsChar.Key == GTL_KEY_ENTER)
	{
		EditBox* eb = (EditBox*)gMain->GetControlByPath("text");

		eastl::string str = eb->GetText();

		if (str != "")
		{
			DataNodeWilson w;
			w["type"] = "chat";
			w["text"] = eb->GetText();

			net->SendToServer(w);

			eb->SetText("");
		}
	}
	else if (event.EventID == Network::Event::ClientPacket)
	{
		tn_packet* packet = (tn_packet*)event.AsVoidPtr;
		SummonerGame::Player* from = FindPlayer(event.SenderConnection()->ConnectionID);

		DataNodeWilson w;
		w.Parse(packet->data);
		eastl::string type = w["type"];

		if (from)
			DoPlayerPacket(from, w, type);
		else 
			DoConnectionPacket(event.SenderConnection(), w, type);

		net->DestroyPacket(packet);
	} 
	else if (event.EventID == Network::Event::ServerPacket)
	{
		tn_packet* packet = (tn_packet*)event.AsVoidPtr;

		DataNodeWilson w;
		w.Parse(packet->data);
		eastl::string type = w["type"];

		DoServerPacket(w, type);

		net->DestroyPacket(packet);
	}

	return 0;
}

int ModeLobby::Unload()
{
	return 0;
}

int ModeLobby::Update( float dt )
{
	Button* ready = (Button*)gMain->GetControlByPath("ready");
	ready->Enabled  = ParentGame->Players.size() == ParentGame->MaxPlayers;
	
	/// Disable ready button when everybody ready
	if (EverybodyReady())
		ready->Enabled = false;
	
	return 0;
}

void ModeLobby::DoPlayerPacket( SummonerGame::Player* from, DataNodeWilson& data, const eastl::string& type )
{
	/// From player
	if (type == "chat")
	{
		DataNodeWilson w;
		w["type"] = "chat";
		w["text"] = GTL::Strings::Printf("<%s> %s", from->Name.c_str(), data["text"].ValueAsString().c_str());
		net->SendToPlayers(w);
	}
	else if (type == "ready")
	{
		from->Ready = data["val"] == "yes";

		DataNodeWilson w;
		w["type"] = "ready";
		w["player"] = from->ID;
		w["val"] = from->Ready?"yes":"no";

		ParentGame->SendToPlayers(w);

		if (EverybodyReady())
		{

		}
	}
	else
	{
		printf("Unknown packet:\n");
		printf("%s\n", data.Encode().c_str());
	}
}

void ModeLobby::DoConnectionPacket( ClientConnection* conn, DataNodeWilson& w, const eastl::string& type )
{
	if (type == "conn")
	{
		if (ParentGame->Players.size() == ParentGame->MaxPlayers)
		{
			conn->SendString("{type=no,reason='Maximum players reached'}");
			conn->Close();
			return;
		}

		SummonerGame::Player& pl = ParentGame->Players.push_back();
		pl.ID = conn->ConnectionID;
		pl.ConnToServer = conn;
		pl.Name = w["name"];
		pl.Ready = false;

		DataNodeWilson np;
		np["type"] = "newplayer";
		np["name"] = pl.Name;
		np["id"] = pl.ID;
		ParentGame->SendToPlayers(np);

		DataNodeWilson cp;
		cp["type"] = "chat";
		cp["text"] = GTL::Strings::Printf("Connected player %s", from->Name.c_str());
		ParentGame->SendToPlayers(cp);
	}
}

void ModeLobby::DoServerPacket( GTL::Structures::DataNodeWilson& w, const eastl::string& type )
{
	if (type == "chat")
	{
		eastl::string text = w["text"];
		TextBox* cb = (TextBox*)gMain->GetControlByPath("chat");

		ChatText += text + "\n";
		cb->SetLabel(ChatText.c_str());
	}
	else if (type == "newplayer")
	{

	}
	else if (type == "ready")
	{
		int id = w["id"];
		bool ready = w["val"] == "yes";
		ParentGame->FindPlayer(id)->Ready = ready;
		if (id == ParentGame->ClientID)
		{
			Button* ready = (Button*)gMain->GetControlByPath("ready");
			ready->SetActive(ready);
		}
	}
	else if (type == "start")
	{
		ParentGame->SetNext('game');
	}
}

bool ModeLobby::EverybodyReady()
{
	int ready = 0;
	
	for (size_t i=0; i<ParentGame->Players.size(); i++)
	{
		if (ParentGame->Players[i].Ready) ready++;
	}
	return ready == ParentGame->Players.size();
}